package com.fzu.geometa.validate.service;

import com.fzu.geometa.validate.dao.TestRecord;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class TestRecordService {
    @Value("${test-record-file}")
    private String recordFile;
    @Value("${test-output}")
    private String testOutput;
    private AtomicInteger nextId;

    private List<TestRecord> cache;

    public List<TestRecord> getAll() {
        if (cache == null) {
            try {
                cache = getAllByFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return cache;
    }

    private List<TestRecord> getAllByFile() throws IOException {
        File csvFile = new File(recordFile);

        List<TestRecord> testRecords = new LinkedList<>();
        Reader in = new FileReader(csvFile);
        Iterable<CSVRecord> records = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(in);
        for (CSVRecord r : records) {
            TestRecord tr = new TestRecord();
            tr.setId(r.get("id"));
            tr.setDataType(r.get("dateType"));
            tr.setTestName(r.get( "testName"));
            tr.setTime(r.get("time"));
            testRecords.add(tr);
        }
        return testRecords;
    }

    public boolean save(TestRecord tr) {
        String id = String.format("S%03d", nextId.get());
        tr.setId(id);
        if (saveToFile(tr)) {
            cache.add(tr);
            nextId.incrementAndGet();
            return true;
        } else {
            return false;
        }
    }

    public boolean del(String id) {
        TestRecord deleted = null;
        for (TestRecord record : cache) {
            if (record.getId().equals(id)) {
                deleted = record;
                cache.remove(deleted);
                break;
            }
        }
        // 删除文件夹
        Path path = Paths.get(testOutput, id);
        try {
            deleteDirs(path);
            // 更新记录文件
            updateFile();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public boolean saveToFile(TestRecord tr) {
        try (CSVPrinter printer = new CSVPrinter(new FileWriter(recordFile,true), CSVFormat.DEFAULT)) {
            printer.printRecord(tr.getId(),tr.getDataType(),tr.getTestName(),tr.getTime());
        } catch (IOException ex) {
            ex.printStackTrace();
            return false;
        }
        return true;
    }

    // 更新文件和目录
    public void updateFile() throws IOException {
        try (CSVPrinter printer = new CSVPrinter(new FileWriter(recordFile,false), CSVFormat.DEFAULT)) {
            printer.printRecord("id", "dateType", "testName", "time");
            for (TestRecord r : cache) {
                printer.printRecord(r.getId(),r.getDataType(),r.getTestName(),r.getTime());
            }
        } catch (IOException ex) {
            throw ex;
        }
    }

    // 下一个可用 id
    public int nextId() throws IOException {
        int id = 1;
        // 先去 cache 中找
        if (cache != null) {
            for (TestRecord tr : cache) {
                int cid = Integer.parseInt(tr.getId().substring(1));
                id = Math.max(id,cid);
            }
            return id;
        }

        // 再去文件中找
        File csvFile = new File(recordFile);
        // 文件不存在
        if (!csvFile.exists()) {
            Path path = Paths.get(recordFile);
            path.getParent().toFile().mkdirs();
            csvFile.createNewFile();
            CSVPrinter printer = new CSVPrinter(new FileWriter(csvFile), CSVFormat.DEFAULT);
            printer.printRecord("id", "dateType", "testName", "time");
            printer.close();
            return id;
        }

        List<TestRecord> testRecords = new ArrayList<>();
        Reader in = new FileReader(csvFile);
        Iterable<CSVRecord> records = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(in);

        // 没有内容
        if (!records.iterator().hasNext()) {
            return id;
        }

        for (CSVRecord r : records) {
            String sid = r.get("id");
            int i = Integer.parseInt(sid.substring(1));
            id = Math.max(id,i);
        }
        id++;
        return id;
    }

    @PostConstruct
    void init() throws IOException {
        int i = nextId();
        nextId = new AtomicInteger(i);
        // 初始化 cache
        cache = getAllByFile();
    }

    //  删除多级目录
    void deleteDirs(Path path) throws IOException {
        Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                    throws IOException {
                Files.delete(file);
                return super.visitFile(file, attrs);
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                    throws IOException {
                Files.delete(dir);
                return super.postVisitDirectory(dir, exc);
            }
        });
    }
}
